package com.xb.loan.util.qrtz.common.store;

import com.xb.loan.util.json.JsonUtils;
import com.xb.loan.util.log.DefaultLoggerFacotry;
import com.xb.loan.util.qrtz.TaskScheduleManager;
import com.xb.loan.util.qrtz.common.Constants;
import com.xb.loan.util.qrtz.common.bean.TaskEntity;
import com.xb.loan.util.qrtz.task.AbstractCronTask;
import com.xb.loan.util.qrtz.task.AbstractSimpleTask;
import com.xb.loan.util.qrtz.task.AbstractTask;
import com.xb.loan.util.qrtz.task.Task;
import org.quartz.DateBuilder;
import org.slf4j.Logger;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * 
 * 任务实体持久化操作类
 * @author hyd
 */
public class TaskEntiryStoreSupport extends JdbcDaoSupport implements SqlTemplate {

	private Logger logger = DefaultLoggerFacotry.getLogger(TaskEntiryStoreSupport.class);

	private TaskScheduleManager taskScheduleManager;
	
	private String tablePrefix;

	public TaskScheduleManager getTaskScheduleManager() {
		return taskScheduleManager;
	}

	public void setTaskScheduleManager(TaskScheduleManager taskScheduleManager) {
		this.taskScheduleManager = taskScheduleManager;
	}

    public String getTablePrefix() {
        return tablePrefix;
    }

    public void setTablePrefix(String tablePrefix) {
        this.tablePrefix = tablePrefix;
    }

    public static String rtp(String query, String tablePrefix) {
        return MessageFormat.format(query, new Object[] { tablePrefix });
    }
	/**
	 * 
	 * 增加新任务实体
	 * @param task
	 */
	public void addTaskEntiry(Task task) {
        String id = task.getTaskEntityId();
        String task_type = Constants.Types.SIMPLE.toString();
        String cron = "";
        long fire_time = -1;
        if (task instanceof AbstractCronTask) {
            task_type = Constants.Types.CRON.toString();
            cron = ((AbstractCronTask) task).getCron_expression();
        } else if (task instanceof AbstractSimpleTask) {
            Date startTime = ((AbstractSimpleTask) task).getStartTime();
            if (startTime == null) {
                int delay_second = ((AbstractSimpleTask) task).getDelay_second();
                if (delay_second == 0) delay_second = 1;
                startTime = DateBuilder.nextGivenSecondDate(null, delay_second);
            }
            fire_time = startTime.getTime();
        }
        String gameId=((AbstractTask)task).getGame_id();
        String issue_id=((AbstractTask)task).getIssue_id();
        String task_desc=((AbstractTask)task).getJobName();
		getJdbcTemplate()
				.update(rtp(insertTaskEntirySql,tablePrefix),
						new Object[] { id,new Date(),fire_time, task_type, cron,
								Constants.Status.WAITING.toString(), task.getClass().getName(),
								JsonUtils.toJson(((AbstractTask) task).getParams(), false),gameId==null?"":gameId,issue_id==null?"":issue_id ,task_desc});

	}

	/**
	 * 
	 * 更新任务实体对象
	 * @param task
	 * @param isComplete
	 */
	public void updateTaskEntiry(Task task, boolean isComplete) {
		String id = task.getTaskEntityId();
		if (isComplete) {
			String task_status = Constants.Status.COMPLETE.toString();
			if (task instanceof AbstractCronTask) {
				task_status = Constants.Status.EXECUTING.toString();
			}
			getJdbcTemplate().update(rtp(updateTaskEntitySql,tablePrefix), new Object[] { new Date(), task_status, id });
		} else {
			getJdbcTemplate().update(rtp(updateTaskEntityWithoutHostSql,tablePrefix),
					new Object[] { new Date(), Constants.Status.EXECUTING.toString(), taskScheduleManager.getHost(), id });
		}
	}

	
	/**
     * 
     * 更新任务实体对象状态
     */
    public void updateTaskEntiryForStatus(String  taskEntityId, String task_status) {
            getJdbcTemplate().update(rtp(updateTaskEntitySql,tablePrefix), new Object[] { new Date(), task_status,taskEntityId });
    }
    
    
    /**
     * 
     * 更新任务实体对象状态
     */
    public void updateTaskEntiryForDelayTimeAndData(String  taskEntityId, String task_status,long delayTime,String task_data) {
            getJdbcTemplate().update(rtp(updateTaskEntiryFordelayTimeAndDataSql,tablePrefix), new Object[] {  task_status,delayTime,task_data,taskEntityId });
    }
    
    /**
     * 
     * 更新任务实体对象
     */
    public void updateTaskEntiryForCronAndData(String  taskEntityId, String task_status,String cron,String task_data) {
            getJdbcTemplate().update(rtp(updateTaskEntityForCronAndDataSql,tablePrefix), new Object[] { task_status, cron,task_data,taskEntityId });
    }

	/**
	 * 
	 * 任务是否存在
	 * @param task
	 * @return
	 */
	public boolean taskIsExists(Task task) {
		return getTaskEntity(task) != null;
	}
	/**
     * 
     * 根据任务 获取任务实体对象
     * @return
     */
	public TaskEntity getTaskEntity(Task task) {
		return getTaskEntity(task.getTaskEntityId());
	}

	/**
	 * 
	 * 根据id获取任务实体对象
	 * @param id
	 * @return
	 */
	public TaskEntity getTaskEntity(String id) {
		TaskEntity task = null;
		try {
			task = getJdbcTemplate().queryForObject(rtp(selectTaskEntityByIdSql,tablePrefix), new Object[] { id }, new TaskRowMapper());
		} catch (org.springframework.dao.EmptyResultDataAccessException ex) {
		} catch (Exception e) {
			logger.error("", e);
		}
		return task;
	}

	/**
	 * 
	 * 获取超过设定阀值时间，没有执行的任务实体对象
	 * @return
	 */
	public List<TaskEntity> getMisFireTaskEntity() {
		List<TaskEntity> list = null;
		try {
			list = (List<TaskEntity>) getJdbcTemplate().query(rtp(selectMisFireTaskEntitySql,tablePrefix),
					new Object[] { System.currentTimeMillis() - taskScheduleManager.getMisfiretime(),"WAITING","SIMPLE" },
					new TaskRowMapper());
		} catch (org.springframework.dao.EmptyResultDataAccessException ex) {
		} catch (Exception e) {
			logger.error("", e);
		}
		return list;
	}

	class TaskRowMapper implements RowMapper<TaskEntity> {
		public TaskEntity mapRow(ResultSet rs, int arg1) throws SQLException {
			TaskEntity tempEntity = new TaskEntity();
			tempEntity.setClassName(rs.getString("class"));
			tempEntity.setCron(rs.getString("cron"));
			tempEntity.setTask_status(rs.getString("task_status"));
			tempEntity.setTask_type(rs.getString("task_type"));
			tempEntity.setId(rs.getString("id"));
			tempEntity.setTask_date(JsonUtils.fromJson(rs.getString("task_data"), HashMap.class));
			tempEntity.setFireTime(rs.getString("fire_time"));
			return tempEntity;
		}
	}

}
